/**
 * @fileOverview firefly提供Javascript扩展
 * @author <a href="mailto:lexloo@126.com">lexloo</a>
 */

(function() {
	if (typeof $Lang != 'undefined') {
		return;
	}

	/**
	 * @static
	 * @class 核心语言扩展类
	 * @author <a href="mailto:lexloo@126.com">lexloo</a>
	 */
	com.firefly.Lang = {
		/**
		 * 判断对象是否为Array
		 * 
		 * @since 1.0
		 * @public
		 * @param {Object}
		 *            o 对象
		 * @returns {Boolean} o为数组则为true，否则false
		 */
		isArray : function(o) {
			if (o) {
				return $Lang.isNumber(o.length) && $Lang.isFunction(o.splice);
			}

			return false;
		},

		/**
		 * 判断对象是否为Boolean
		 * 
		 * @public
		 * @since 1.0
		 * @param {Object}
		 *            o 判断的对象
		 * @return {Boolean} o为Boolean则为true，否则false
		 */
		isBoolean : function(o) {
			return typeof o === 'boolean';
		},

		/**
		 * 判断对象是否为Function
		 * 
		 * @public
		 * @since 1.0
		 * @param {Object}
		 *            o 判断的对象
		 * @return {Boolean} o为Function则为true，否则false
		 */
		isFunction : function(o) {
			return typeof o === 'function';
		},

		/**
		 * 判断对象是否为null
		 * 
		 * @public
		 * @since 1.0
		 * @param {Object}
		 *            o 判断的对象
		 * @return {Boolean} o为null则为true，否则false
		 */
		isNull : function(o) {
			return o === null;
		},

		/**
		 * 判断对象是否Number
		 * 
		 * @public
		 * @since 1.0
		 * @param {Object}
		 *            o 判断的对象
		 * @return {Boolean} o为Number则为true，否则false
		 */
		isNumber : function(o) {
			return typeof o === 'number' && isFinite(o);
		},

		/**
		 * 判断对象是否为Object
		 * 
		 * @public
		 * @since 1.0
		 * @param {Object}
		 *            o 判断的对象
		 * @return {Boolean} o为Object则为true，否则false
		 */
		isObject : function(o) {
			return (o && (typeof o === 'object' || $Lang.isFunction(o))) || false;
		},

		/**
		 * 判断对象是否为String
		 * 
		 * @public
		 * @since 1.0
		 * @param {Object}
		 *            o 判断的对象
		 * @return {Boolean} o为String则为true，否则false
		 */
		isString : function(o) {
			return typeof o === 'string';
		},

		/**
		 * 判断对象是否为undefined
		 * 
		 * @public
		 * @since 1.0
		 * @param {Object}
		 *            o 判断的对象
		 * @return {Boolean} o为undefined则为true，否则false
		 */
		isUndefined : function(o) {
			return typeof o === 'undefined';
		},

		/**
		 * 判断对象是否为值(Value)
		 * 
		 * @public
		 * @since 1.0
		 * @param o
		 *            {Object} 判断的对象
		 * @return {Boolean} 如果不为 null/undefined/NaN || false 时为真
		 */
		isValue : function(o) {
			return ($Lang.isObject(o) || $Lang.isString(o) || $Lang.isNumber(o) || $Lang.isBoolean(o));
		},

		/**
		 * 对象属性复制
		 * 
		 * @public
		 * @since 1.0
		 * @param {Object}
		 *            obj 属性接收者
		 * @param {Object}
		 *            config 属性提供值者
		 * @param {Object}
		 *            [defaults] 默认属性提供者
		 * @return {Object} 对象
		 */
		apply : function(o, c, defaults) {
			if (defaults) {
				$Lang.apply(o, defaults);
			}

			if (o && c && $Lang.isObject(c)) {
				for ( var p in c) {
					o[p] = c[p];
				}
			}
		},

		/*
		 * IE will not enumerate native functions in a derived object even if
		 * the function was overridden. This is a workaround for specific
		 * functions we care about on the Object prototype. @param {Function} r
		 * the object to receive the augmentation @param {Function} s the object
		 * that supplies the properties to augment @private
		 */
		/*
		 * __IEEnumFix: function(r, s) { if (org.antlr.env.ua.ie) { var
		 * add=["toString", "valueOf"], i; for (i=0;i<add.length;i=i+1) { var
		 * fname=add[i],f=s[fname]; if (org.antlr.lang.isFunction(f) &&
		 * f!=Object.prototype[fname]) { r[fname]=f; } } } },
		 */
		/**
		 * 建立继承机制,包括原型、构造器、超类属性，静态对象不继承
		 * 
		 * @public
		 * @since 1.0
		 * @param {Function}
		 *            subc 子类
		 * @param {Function}
		 *            superc 父类
		 * @param {Object}
		 *            [overrides] 其它属性/方法,覆盖超类提供的属性/方法。
		 */
		extend : function(subc, superc, overrides) {
			if (!superc || !subc) {
				throw new Error("$Lang.extend 失败, 请检查包括所有依赖。");
			}
			var F = function() {
			};
			F.prototype = superc.prototype;
			subc.prototype = new F();
			subc.prototype.constructor = subc;
			subc.superclass = superc.prototype;
			if (superc.prototype.constructor == Object.prototype.constructor) {
				superc.prototype.constructor = superc;
			}

			if (overrides) {
				for ( var i in overrides) {
					subc.prototype[i] = overrides[i];
				}

				/* IE 可能不会复制toString， valueOf相关函数 */
				/* com.priorbi.lang._IEEnumFix(subc.prototype, overrides); */
			}
		}
	};

	/**
	 * 可迭代数据转化为数组
	 * 
	 * @since 1.0
	 * @param {Object}
	 *            o 可迭代数据
	 */
	$A = function(o) {
		if (!o)
			return [];
		if (o.toArray)
			return o.toArray();
		var length = o.length, results = new Array(length);
		while (length--)
			results[length] = o[length];

		return results;
	};

	/**
	 * 可迭代数据转化为数组,如果是单个值，转化为数组的第一个值
	 * 
	 * @since 1.0
	 * @param {Object}
	 *            o 可迭代数据
	 */
	$AA = function(o) {
		result = $A(o);

		if (o) {
			if (result[0] == undefined) {
				result[0] = o;
			}
		}

		return result;
	};

	/**
	 * com.firefly.Lang的的快捷访问
	 * 
	 * @since 1.0
	 */
	$Lang = com.firefly.Lang;

	/* Array扩充 */
	/**
	 * 依次对Array对象所有对象进行处理
	 * 
	 * @since 1.0
	 * @param {Function}
	 *            iterator 处理函数
	 * @param {Function}
	 *            [context] 上下文
	 */
	Array.prototype.each = function(iterator, context) {
		iterator = iterator.bind(context);
		for ( var i = 0, length = this.length; i < length; i++) {
			try {
				iterator(this[i], i);
			} catch (e) {
				throw e;
			}
		}
	};

	/**
	 * 依次对Array所有对象进行处理，当第一个返回结果不为空时终止,并返回该结果。
	 * 
	 * @since 1.0
	 * @param {Function}
	 *            iterator 处理函数
	 * @param {Function}
	 *            [context] 上下文
	 */
	Array.prototype.eachF = function(iterator, context) {
		var result;

		iterator = iterator.bind(context);
		for ( var i = 0, length = this.length; i < length; i++) {
			try {
				result = iterator(this[i], i);

				if (result != undefined)
					return result;

			} catch (e) {
				throw e;
			}
		}
	};

	/**
	 * 删除数组指定位置的元素
	 * 
	 * @since 1.0
	 * @param {Number}
	 *            index 位置
	 */
	Array.prototype.remove = function(index) {
		if (isNaN(index) || index > this.length) {
			return false;
		}
		this.splice(index, 1);
	};

	/**
	 * 删除最后一个元素
	 * 
	 * @since 1.0
	 */
	Array.prototyperemoveLast = function() {
		this.remove(this.length - 1);
	};

	/**
	 * 判断元素在Array中的序号
	 * 
	 * @since 1.0
	 * @param {Object}
	 *            o 目标对象
	 * @returns {Integer} 对象在Array中的序号，第一位为0，如果没在Array中则结果为-1
	 */
	Array.prototype.indexOf = function(o) {
		for ( var i = 0, length = this.length; i < length; i++) {
			if (this[i] == o) {
				return i;
			}
		}

		return -1;
	};

	/**
	 * 判断Array是否包含指定对象
	 * 
	 * @since 1.0
	 * @param {Object}
	 *            o 目标对象
	 * @returns {Boolean} 如果包含目标对象则为true，否则为false
	 */
	Array.prototype.contains = function(o) {
		return this.indexOf(o) > -1;
	};

	/**
	 * 清空Array
	 * 
	 * @since 1.0
	 * @return 当前数组
	 */
	Array.prototype.clear = function() {
		this.length = 0;
		return this;
	};

	/**
	 * Array对象不包含元素
	 * 
	 * @since 1.0
	 * @returns 不包含元素时为true，否则为false
	 */
	Array.prototype.isEmpty = function() {
		return 0 == this.length;
	};

	/**
	 * 对象转换成字符串,如果为null或undefined则转换为空
	 * 
	 * @since 1.0
	 * @param {Object}o
	 *            对象
	 * @returns 字符串
	 */
	String.convert = function(o) {
		var defValue = arguments[1] ? arguments[1] : '';

		if (o == null || o == undefined) {
			return defValue;
		} else {
			if (o.toString) {
				return o.toString();
			} else {
				return defValue;
			}
		}
	};

	/* String 扩充 */

	/**
	 * 字符串驼峰表示
	 * 
	 * @returns {String} 字符串驼峰表示
	 */
	String.prototype.camelize = function() {
		var parts = this.split('-'), len = parts.length;
		if (len == 1)
			return parts[0];

		var camelized = this.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0];

		for ( var i = 1; i < len; i++)
			camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

		return camelized;
	};

	/**
	 * 字符串首字母大写，其余小写
	 * 
	 * @returns {String} 字符串
	 */
	String.prototype.capitalize = function() {
		return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
	};

	/**
	 * 清除字符串两端空格
	 * 
	 * @returns {String} 字符串
	 */
	String.prototype.trim = function() {
		return this.replace(/(^\s*)|(\s*$)/g, "");
	};

	/**
	 * 清除字符串左端空格
	 * 
	 * @returns {String} 字符串
	 */
	String.prototype.ltrim = function() {
		return this.replace(/(^\s*)/g, "");
	};

	/**
	 * 清除字符串右端空格
	 * 
	 * @returns {String} 字符串
	 */
	String.prototype.rtrim = function() {
		return this.replace(/(\s*$)/g, "");
	};

	/**
	 * 判断字符串是否包含子串
	 * 
	 * @param {String}
	 *            text 子串
	 * @returns {Boolean} 如果包含则为true，否则为false
	 */
	String.prototype.include = function(pattern) {
		return this.indexOf(pattern) > -1;
	};

	/**
	 * 判断字符串是否以指定字符串开始
	 * 
	 * @param pattern
	 *            指定字符串
	 * @returns {Boolean} 以指定字符串开始则为true，否则为false
	 */
	String.prototype.startsWith = function(pattern) {
		return this.indexOf(pattern) === 0;
	};

	/**
	 * 判断字符串是否以指定字符串结束
	 * 
	 * @param pattern
	 *            指定字符串
	 * @returns {Boolean} 以指定字符串结束则为true，否则为false
	 */
	String.prototype.endsWith = function(pattern) {
		var d = this.length - pattern.length;
		return d >= 0 && this.lastIndexOf(pattern) === d;
	};

	/**
	 * 判断字符串是否为空
	 * 
	 * @returns {Booelan} 如果为空则为true，否则为false
	 */
	String.prototype.isEmpty = function() {
		return this == '';
	};

	/**
	 * 替换所有子串
	 * 
	 * @param findText
	 *            查找字符串
	 * @param repText
	 *            替换的字符串
	 * @return {String} 替换后的字符串
	 */
	String.prototype.replaceAll = function(findText, repText) {
		return this.replace(new RegExp(findText, 'gm'), repText);
	};

	/**
	 * 格式化字符串
	 * 
	 * @example 'hello, My name is {0} {1}.'.format(firstName, lastName);
	 * @return {String} 格式化后的字符串
	 */
	String.prototype.format = function() {
		if (arguments.length == 0) {
			return this;
		} else {
			var str = this;
			for ( var i = 0; i < arguments.length; i++) {
				str = str.replaceAll('\\{' + i + '\\}', arguments[i]);
			}

			return str;
		}
	};

	/**
	 * 以逗号分隔的字符串转化为数组
	 * 
	 * @return {Array} 数组
	 */
	String.prototype.toArray = function() {
		return this.split(',');
	};

	/**
	 * 过滤Tags
	 * 
	 * @return {String} 字符串
	 */
	String.prototype.stripTags = function() {
		return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
	};

	/**
	 * 替换HTML符号
	 * 
	 * @return {String} 字符串
	 */
	String.prototype.escapeHTML = function() {
		return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
	};

	/**
	 * 恢复HTML符号
	 * 
	 * @return {String} 字符串
	 */
	String.prototype.unescapeHTML = function() {
		return this.stripTags().replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&').replace(/&quot;/g,
				'"');
	};

	/* 扩充Function功能 */
	/**
	 * 绑定函数到上下文环境
	 * 
	 * @since 1.0
	 * @returns {Function} 函数
	 */
	Function.prototype.bind = function() {
		if (arguments.length < 2 && arguments[0] === undefined)
			return this;
		var __method = this, args = $A(arguments), object = args.shift();
		return function() {
			return __method.apply(object, args.concat($A(arguments)));
		};
	};

	/**
	 * 绑定函数到事件监听
	 * 
	 * @since 1.0
	 * @returns {Function} 函数
	 */
	Function.prototype.bindAsEventListener = function() {
		var __method = this, args = $A(arguments), object = args.shift();
		return function(event) {
			return __method.apply(object, [ event || window.event ].concat(args));
		};
	};
})();